#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>


//1 设计一个小程序来判断当前机器的字节序


//int check_sys()
//{
//	int a = 1;//用创的一个整型变量来判断这个程序
//	return *(char*)&a;//&a载体是首字节地址即低地址开头地址
//}//返回1是小端，返回0是大端
//
//int main()
//{          //数值高位   //低位
//	int a = 1;//0x00 00 00 01 -- a的数值的十六进制形式
//	//a变量的内存存储形式
//  //低地址   高地址
//	//00 00 00 01 -- 大端字节序排序存储
//	//01 00 00 00 -- 小端字节序排序存储
//	//看看变量的内存的首字节低地址存的是什么判断
//	if (*(char*)&a == 1)
//	{
//		printf("小端\n");
//	}
//	else
//		printf("大端\n");
//
//	if (check_sys() == 1)
//		printf("小端\n");
//	else
//		printf("大端\n");
//	return 0;
//}


//2


//int main()
//{
//	//-1二进制表示
//	//10000000000000000000000000000001 - 原码
//	//11111111111111111111111111111110 - 反码
//	//11111111111111111111111111111111 - 补码 <- 1个字节8个bit从低位截断8位放
//	//11111111 - a的补码
//	//%d打印a的时候不够一个整型，打印的时候要发生整型提升升为int类型(有符号的)；unsigned int 无符号类型，与正整数一样原反补一致
//	char a = -1;//char 默认为signed char，有符号，整型提升对其补码进行符号扩展，高位补符号位
//	//第一个1为符号位
//	//11111111111111111111111111111111 -a整型提升完后的补码
//	//10000000000000000000000000000001 -转化(有符号负整数的转化)为原码看数值，是-1
//	signed char b = -1;//vs这里signed char 与 char 一样的
//	unsigned char c = -1;
//	//-1补码截取8位放
//	//11111111 -c的补码
//	//%d打印signed int整型，就要对c进行整型提升，把c由小整型类型unsigned char提升为(signed)int整型类型
//	//unsigned char无符号整数,没有符号位，整型提升时简单补0
//	//00000000000000000000000011111111 - 提升后c的补码
//	//00000000000000000000000011111111 - 提升后c的原码 无符号整数的原、反、补码相同 原码读出数值是255
//	//%d打印有符号整数来判定时看c的原码，符号位是0是一个正数，255
//	//首位是0，原反补相同；首位1，原取反加1得补码
//	printf("a=%d,b=%d,c=%d", a, b, c);
//	//-1 -1 255
//	//%d - 打印有符号(正数、0、负数)的整数，按照有符号数打印
//	//%u - 打印无符号(正数、0)的整数
//	return 0;
//}


//3


//int main()
//{
//	char a = -128;
//	//1000000000000000000000010000000 ->-128原码
//	//1111111111111111111111101111111 ->-128反码
//	//1111111111111111111111110000000 ->-128补码
//	//10000000 ->a的补码
//	//a是有符号小整型char(signed char)
//	//11111111111111111111111110000000 ->a整型提升后的补码
//	//交互时是在内存中以补码形式交互的
//	//11111111111111111111111110000000 ->%u接整型提升后的补码
//	//%u打印无符号数的，视接过来的码为无符号码，无符号码也一样原反补相同；无符号数和正数一个道理的
//	//11111111111111111111111110000000 ->%u打印的原码,是个非常大的数
//	printf("%u\n", a);
//	//%u打印unsigned int类型的，按照无符号数(全是数值位，没有符号位)打印，a整型提升后的原码的首位也是看做是数值位打了，是个巨大的数，4294967168
//	//%u打印无符号的整数，%u的角度，它认为内存中存储的是无符号的整数
//
//	printf("%d\n", a);
//	//11111111111111111111111110000000 ->a整型提升后的补码
//	//11111111111111111111111110000000 ->%d接整型提升后的补码
//	//10000000000000000000000001111111
//	//10000000000000000000000010000000 ->补码转原码，还是-128的原码
//
//	char b = 128;
//	//00000000000000000000000010000000 ->128原码
//	//01111111111111111111111101111111 ->128反码
//	//01111111111111111111111110000000 ->128补码
//	//10000000 ->截取8位，b的补码
//	//11111111111111111111111110000000 ->b整型提升后的补码，%d接的补码,%d视有符号的视有符号位的，首位符号位是1是负数，取反+1转原码(首位是0的话直接等于原码)
//	//10000000000000000000000010000000 ->%d接的补码转原码，是-128
//	printf("%d\n", b);
//
//	//01111111111111111111111110000000 ->128补码
//	//10000000 ->截取8位，b的补码
//	//11111111111111111111111110000000 ->b整型提升后的补码，%u接过来的补码
//	//11111111111111111111111110000000 ->%u原反补码相同，原码显示是个非常大的数
//	printf("%u\n", b);
//	return 0;
//}


//4 数值的补码放入存值变量补码(有性质)，存值变量补码放入使用视角补码(有性质，覆盖前面性质)，补码内容稳定传
//值+使用视角性质即可确定，与值存放地方变量性质没关系它是会被覆盖的
//使用视角性质与变量类型性质一致能保持显此变量存此值的展的意义与创建时的目的，维持其来的预想的形式上意义


//int main()
//{
//	signed int num = -10;
//	//10000000000000000000000000001010 ->-10原码
//	//11111111111111111111111111110101 ->-10反码
//	//11111111111111111111111111110110 ->-10补码
//	//11111111111111111111111111110110 ->-10放入signed int num的补码
//
//	printf("%d\n", num);
//	//11111111111111111111111111110110 ->%d接过signed int num内的补码
//	//10000000000000000000000000001001 ->反码
//	//10000000000000000000000000001010 ->原码 ->-10
//
//	//11111111111111111111111111110110 ->%u接过signed int num内的补码
//	//11111111111111111111111111110110 ->反码
//	//11111111111111111111111111110110 ->补码 ->4294967286
//	printf("%u\n", num);
//
//	unsigned int num2 = -10;
//	//10000000000000000000000000001010 ->-10原码
//	//11111111111111111111111111110101 ->-10反码
//	//11111111111111111111111111110110 ->-10补码
//	//11111111111111111111111111110110 ->-10放入unsigned int num2内的补码
//	
//	//-10补码内容不变，补码内容放入存值变量里内容也是不变(性质可能变),使用视角的性质最终决定其性质，-10补码内容固定不变确定下来的，固定传到最后，性质是最后使用视角的性质
//	
//	//11111111111111111111111111110110 ->%d接过unsigned int num2内的补码
//	//10000000000000000000000000001001 ->反码
//	//10000000000000000000000000001010 ->原码 ->-10
//	printf("%d\n", num2);
//
//	//11111111111111111111111111110110 ->%u接过unsigned int num2内的补码
//	//11111111111111111111111111110110 ->反码
//	//11111111111111111111111111110110 ->原码 ->4294967286
//	printf("%u\n", num2);
//	return 0;
//}


//4


//#include<string.h>
//int main()
//{
//	char a[1000];
//	for (int i = 0;i < 1000;i++)
//	{
//		a[i] = -1 - i;
//		//整数-1的补码是10000000000000000000000000000001
//		//              11111111111111111111111111111110
//		//              11111111111111111111111111111111
//		//                                10000001
//		//                                10000000
//		//补码存到char a[0]时截取后8位也是11111111数值表示也是-1，-1到-128整型的数是怎样的最后存到char中表示的也还是怎样的（整型的-128 ->10000000000000000000000010000000补码存到char时10000000，char里面转原码时 ->是00000000读成-128，也保持了整型的值存放后不变)11111111111111111111111101111111              11111111                               
//	}//            11111111111111111111111110000000             100000000
//	//-127放时  10000000000000000000000001111111补码的10000001放到char    原码读的都一样读的都是前7位，符号位都是1，数值最终一致，读的一致
//	//          11111111111111111111111110000000      11111110
//	//          11111111111111111111111110000001      11111111
//	//但-129放时10000000000000000000000010000001存到char里的01111111，-129整型原码读的是前8位，符号位是1，读出来的是-129；放到char里时读的是前7位，符号位是0，读出来的是127,数值不一致了
//	//          11111111111111111111111101111110            01111111
//	//          11111111111111111111111101111111            01111111
//	//整型32位第32位是符号位，其余数值值；char空间共有8位，第8位是符号位，其余是数值位
//	//当整型数据的只有前7位有值算且第八位截取后与其符号位一致的，其值放入char后其值不变的
//	printf("%zd\n", strlen(a));//第一次遇到0前的非0个数 128-1+1+127-0 = 255
//	//最终存进去的值一轮一轮的-1到-128再到127到0，然后又开始循环放出这样的结果
//	return 0;
//}


//5
 

//int main()
//{
//	unsigned char i = 0;
//	//0~255     恒成立
//	for (i = 0;i <= 255;i++)
//	{
//		printf("hello world\n");
//	}
//	return 0;
//}


//6


////10000000000000000000000000000001 -> -1原码
////11111111111111111111111111111110 -> -1反码
////11111111111111111111111111111111 -> -1补码
////11111111111111111111111111111111 -> %u接-1补码再转原码也是
////也一样 0 - > 00000000000000000000000000000000 - 1 全改1 -> 11111111111111111111111111111111圈循环效果
//
//                                                                                         //第33位对的是33-1=32次方
////一个整型32位，全是数值位全是1的值是2^32 - 1，因为11111111111111111111111111111111 == 100000000000000000000000000000000 - 1
////unsigned int 是一种无符号整数类型，它不包含负值，因此它的取值范围仅由正整数和零组成。取值范围：0~2^32 - 1
////由于 unsigned int 只表示非负值，所以它能够存储较大的正整数，但无法表示负数。第一位也是数值位全当数值位
//
//#include<Windows.h>
//int main()
//{
//	unsigned int i;
//	for (i = 9;i >= 0;i--)
//	{
//		printf("%u\n", i);
//		Sleep(100);
//	}
//	return 0;
//}


//7


////x86环境 小端字节序
//int main()
//{
//	int a[4] = { 1,2,3,4 };
//	//小端字节序排放 - 数值的高位放在低地址，数值的低位放高地址，一个数值一个数值而言的
////低地址                                   高地址
////01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00  数组内存展开，往里按顺序从低地址到高地址往里放元素的值
////低位   高位
//	int* ptr1 = (int*)(&a + 1);
//	int* ptr2 = (int*)((int)a + 1);//一个地址一个代号表示一个字节的地址
////01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
////   00 00 00 02 ->在内存的小端字节序排的数值 ->我们默认的大端字节序高位到低位读其值 ->02 00 00 00 打印也按我们读的大端字节序的打印 ->%x打印出->2000000(%x打印时前面的0x省,前面的0也省)
//// 地址头，4字节解引用权限
//	printf("%x,%x", ptr1[-1], *ptr2);
//	//%x 是以16进制的形式打印
//	return 0;
//}


//8 整数与浮点数在内存中存储是不一样的


//int main()
//{
//	int n = 9;//00000000000000000000000000001001 -> 9的原反补码
//
//	float* pFloat = (float*)&n;
//	printf("n的值为: %d\n", n);//9
//	printf("*pFloat的值为: %f\n", *pFloat);//以*pFloat角度，它认为指向的是浮点数按照浮点数的视角形式在内存里找，以浮点数的形式找出个值
//	//0   00000000      00000000000000000001001 -> *pFloat视角读浮点内存里存储形式的值，现在要读它表示的值，E处要-127，M头处要补1，小数点补上
//	//+   2^(0-127) * 1.00000000000000000001001
//	//        |         后面都是0*2^(-1)+0*2^(-2)+……+1*2^(-20)+0*2^(-21)+0*2^(-22)+1*2^(-23)
//	// 二进制的科学计数法，管小数点偏移                                                                                   (二进制的)
//	//且针对E为00000000这种全0的，E规定好为是1-127=-126，M处小数点前头也不补1了，更小了无限接近0的数字  -> 2^(-126)*0.00000000000000000001001
//	//所以读出来是0.000000
//	*pFloat = 9.0;
//	//1001.0 -> 9.0的二进制序列
//	//1.001*2^3
//	//(-1)^0 * 1.001 * 2^3
//	//S=0;E=3;M=1.001;   E+127=130   M去1->.001
//	//9.0放进内存里的二进制序列
//	//0 10000010 00100000000000000000000
//	//n打印时它认为是内存里的补码，站的n的角度认为它里面是个整数是整数的补码
//	//正数原反补码相同，原码为01000001000100000000000000000000
//	printf("n的值为: %d\n", n);//所以为1091567616
//	printf("*pFloat的值为: %f\n", *pFloat);//9.000000 -> %f占位符按浮点数视角形式读取内存里的二进制序列
//	return 0;
//}//整数就该用%d打印，小数就该用%f打印，不然永远测试不出结果
 

//9


//int main()
//{
//	float f = 5.5f;
//	//5.5(十进制) == 101.1(二进制) -> 1*2^2 + 0*2^1 + 1*2^0 + 1*2^(-1)
//	                    //==1.011*10^2
//	//S = 0;
//	//E = 2;
//	//M = 1.011     //计算机内部存时开头1.的1是不会存进去的，读取时自动在读的内容前头补一个1读，用23位可以存24位效果
//	//符号位(1位) E(8位)存2+127十进制转二进制  M(23位)直接存二进制的M舍弃开头1.的小数部分，后面补0
//	//   0                10000001                        01100000000000000000000
//	//0100 0000 1011 0000 0000 0000 0000 0000 -> 内存里二进制存储
//	// 4    0    b    0    0    0    0    0  -> 监视里内存十六进制表达存储
//	//40 b0 00 00
//	//00 00 b0 40 ->小端字节序排放
// //始终也还没开始对它读，这些都是它在内存里存形式的内容，到%f读时对内存里存形式的内容进行E处-127，M处小数点前头补1
//	return 0;
//}


//10


// #include<math.h>
// int main()
// {
// 	float f = 3.45;
// 	if (f == 3.45)
// 		printf("相等\n");
// 	else
// 		printf("不相等\n");//存进里的f一定比3.45小，fabs看之间差值大小
// 	if (fabs(f - 3.45) < 0.0000001)
// 		printf("相等\n");
// 	else
// 		printf("不相等\n");

// }